package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"time"
)

type Object struct {
	ID   string
	Hash string
}

const workDir = "/opt/gopath/src/github.com/hyperledger/fabric/peer/"

func greet(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World! %s", time.Now())
}

func query_obj(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	timeStart := time.Now().UnixNano()
	id := r.URL.Query().Get("ID")
	arg_str := "{\"Args\":[\"ReadObject\", \"" + id + "\"]}"
	query_cmd := exec.Command("docker", "exec", "cli0", "peer", "chaincode", "query", "-C", "mychannel", "-n", "basic", "-c", arg_str)

	var outputbuf bytes.Buffer
	query_cmd.Stdout = &outputbuf
	if err := query_cmd.Start(); err != nil {
		_, _ = w.Write([]byte("-1"))
		return
	}
	if err := query_cmd.Wait(); err != nil {
		_, _ = w.Write([]byte("-2"))
		fmt.Printf("<-对象'%s'不存在->\n", id)
		return
	}
	var obj_res Object
	err := json.Unmarshal(outputbuf.Bytes(), &obj_res)
	if err != nil {
		panic(err)
	}
	_, _ = w.Write([]byte(obj_res.Hash))
	fmt.Printf("<-添加对象ID: '%s', Hash: '%s'到Fabric-> 花费时间: %fms\n", obj_res.ID, obj_res.Hash, ((float64)(time.Now().UnixNano()-timeStart))/1e6)
}

func add_obj(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	obj_put := Object{
		ID:   r.FormValue("ID"),
		Hash: r.FormValue("Hash"),
	}
	timeStart := time.Now().UnixNano()
	arg_str := "{\"function\":\"CreateObject\", \"Args\":[\"" + obj_put.ID + "\", \"" + obj_put.Hash + "\"]}"
	invoke_cmd := exec.Command("docker", "exec", "cli0", "peer", "chaincode", "invoke", "-o", "orderer0.demo.com:7050",
		"--ordererTLSHostnameOverride", "orderer0.demo.com", "--tls",
		"--cafile", workDir+"crypto/ordererOrganizations/demo.com/orderers/orderer0.demo.com/msp/tlscacerts/tlsca.demo.com-cert.pem",
		"-C", "mychannel", "-n", "mycc",
		"--peerAddresses", "peer0.org1.demo.com:7051",
		"--tlsRootCertFiles", workDir+"crypto/peerOrganizations/org1.demo.com/peers/peer0.org1.demo.com/tls/ca.crt",
		"--peerAddresses", "peer0.org2.demo.com:7051",
		"--tlsRootCertFiles", workDir+"crypto/peerOrganizations/org2.demo.com/peers/peer0.org2.demo.com/tls/ca.crt",
		"--peerAddresses", "peer0.org3.demo.com:7051",
		"--tlsRootCertFiles", workDir+"crypto/peerOrganizations/org3.demo.com/peers/peer0.org3.demo.com/tls/ca.crt",
		"--peerAddresses", "peer0.org4.demo.com:7051",
		"--tlsRootCertFiles", workDir+"crypto/peerOrganizations/org4.demo.com/peers/peer0.org4.demo.com/tls/ca.crt",
		"-c", arg_str)

	if err := invoke_cmd.Start(); err != nil {
		_, _ = w.Write([]byte("-1"))
		return
	}
	if err := invoke_cmd.Wait(); err != nil {
		_, _ = w.Write([]byte("-2"))
		fmt.Printf("<-添加对象ID: '%s', Hash: '%s'到Fabric失败-> 对象已存在\n", obj_put.ID, obj_put.Hash)
		return
	}
	_, _ = w.Write([]byte("0"))
	fmt.Printf("<-添加对象ID: '%s', Hash: '%s'到Fabric-> 花费时间: %fms\n", obj_put.ID, obj_put.Hash, ((float64)(time.Now().UnixNano()-timeStart))/1e6)
}

func setEnv(workDir string) {
	os.Chdir(workDir)
	os.Setenv("FABRIC_CFG_PATH", workDir+"../config/")
	os.Setenv("CORE_PEER_TLS_ENABLED", "true")
	os.Setenv("CORE_PEER_LOCALMSPID", "Org1MSP")
	os.Setenv("CORE_PEER_TLS_ROOTCERT_FILE", workDir+"organizations/peerOrganizations/org1.demo.com/peers/peer0.org1.demo.com/tls/ca.crt")
	os.Setenv("CORE_PEER_MSPCONFIGPATH", workDir+"organizations/peerOrganizations/org1.demo.com/users/Admin@org1.demo.com/msp")
	os.Setenv("CORE_PEER_ADDRESS", "localhost:7051")
}

func main() {
	fmt.Print("Set OS env ...")
	setEnv(workDir)
	fmt.Println("Done")

	http.HandleFunc("/", greet)
	http.HandleFunc("/get", query_obj)
	http.HandleFunc("/put", add_obj)

	http.ListenAndServe(":8080", nil)
}
